package transform

import (
	"gitee.com/sansaniot/ssiot-core/facade/env"
	js "github.com/dop251/goja"
	"github.com/forestgiant/sliceutil"
	"ssdevice/common/constant"
	"ssdevice/common/utils"
	"ssdevice/internal/rule/model"
	"ssdevice/internal/rule/model/stats"
	"strings"
	"time"
)

const statTable = "sys_history_sensor"

func TransFuncRegister(call js.ConstructorCall) *js.Object {
	call.This.Set("statMinute", StatMinute)
	call.This.Set("statHour", StatHour)
	call.This.Set("statDay", StatDay)
	//call.This.Set("getRealData", GetRealData)
	//call.This.Set("sendLogoutTopic", SendLogoutTopic)
	return nil
}

// StatMinute 统计函数可以在定时处理器中使用，也可以在数据上报处理器中使用
func StatMinute(context map[string]interface{}, variables string) map[string]map[string]interface{} {
	ruleId, _ := context[constant.ContextRuleId].(string)
	sn, _ := context["sn"].(string)

	// 不在规则中的sn不能统计
	if !checkSn(sn, ruleId) {
		return nil
	}

	// 统计变量
	vars := strings.Split(variables, ",")

	//统计时间
	now := time.Now()
	now = now.Truncate(time.Second)
	lastTime := now.Add(-1 * time.Minute)

	// 计算并入库
	return calAndInsertResult(ruleId, sn, vars, lastTime, now, constant.RuleCalMinuteWindow)
}

func StatDay(context map[string]interface{}, variables string) map[string]map[string]interface{} {
	ruleId, _ := context["_reserve_rule_id"].(string)
	sn, _ := context["sn"].(string)

	// 不在规则中的sn不能统计
	if !checkSn(sn, ruleId) {
		return nil
	}

	// 统计设备和变量
	vars := strings.Split(variables, ",")

	//统计时间
	now := time.Now()
	now = now.Truncate(time.Second)
	lastTime := now.Add(-24 * time.Hour)

	// 计算并入库
	return calAndInsertResult(ruleId, sn, vars, lastTime, now, constant.RuleCalDayWindow)
}

func StatHour(context map[string]interface{}, variables string) map[string]map[string]interface{} {
	ruleId, _ := context["_reserve_rule_id"].(string)
	sn, _ := context["sn"].(string)

	// 不在规则中的sn不能统计
	if !checkSn(sn, ruleId) {
		return nil
	}

	// 统计设备和变量
	vars := strings.Split(variables, ",")

	//统计时间
	now := time.Now()
	now = now.Truncate(time.Second)
	lastTime := now.Add(-1 * time.Hour)

	// 计算并入库
	return calAndInsertResult(ruleId, sn, vars, lastTime, now, constant.RuleCalHourWindow)
}

func calAndInsertResult(ruleId string, sn string, vars []string, lastTime time.Time, now time.Time, window string) map[string]map[string]interface{} {
	//统计结果对象缓存
	//resultList := make([]stats.IotStatResult, 0)
	result := make(map[string]map[string]interface{})

	for _, va := range vars {
		//聚合函数查询得到对应的统计结果
		doc := stats.CalBasicAlgos(sn, va, statTable, lastTime, now)
		result[va] = doc
		////统计结果对象
		//statResult := stats.IotStatResult{}
		////基础信息
		//statResult.Id = utils.SimpleUUID()
		//statResult.Window = window
		//statResult.Sn = sn
		//statResult.RuleId = ruleId
		//statResult.Attribute = va
		//statResult.StatTime = lastTime
		//// 统计值
		//statResult.MaxValue = tools.GetDecimalValue(doc, constant.AlgoMax)
		//statResult.MinValue = tools.GetDecimalValue(doc, constant.AlgoMin)
		//statResult.SumValue = tools.GetDecimalValue(doc, constant.AlgoSum)
		//statResult.AvgValue = tools.GetDecimalValue(doc, constant.AlgoAverage)
		//statResult.StartValue = tools.GetDecimalValue(doc, constant.AlgoStart)
		//statResult.EndValue = tools.GetDecimalValue(doc, constant.AlgoEnd)
		//statResult.DiffValue = tools.GetDecimalValue(doc, constant.AlgoDiff)
		//resultList = append(resultList, statResult)
	}
	//stats.BatchInsertStatResult(resultList)
	return result
}

func checkSn(sn, ruleId string) bool {
	// 获得规则信息
	rule := &model.Rule{}
	rule.Orm = env.Db
	_ = rule.GetById(ruleId)
	ruleSns := strings.Split(rule.DevSn, ",")

	if sliceutil.Contains(ruleSns, sn) {
		return true
	}

	productIds := strings.Split(rule.ProductId, ",")
	//查询设备对应产品编码
	devCache, _ := env.Cache.HashGet(constant.DeviceEasyCache, sn)
	if len(devCache) == 0 {
		return false
	}
	info := utils.BytesToMap([]byte(devCache))
	productModel := utils.If(info["productModel"] != nil, info["productModel"], "").(string)
	if len(productModel) == 0 {
		return false
	}
	if sliceutil.Contains(productIds, productModel) {
		return true
	}
	return false
}
